package com.qls.ali.biz.service.fz.impl;

import com.alibaba.fastjson.JSON;
import com.qls.ali.biz.service.fz.Cache;
import com.qls.core.constant.Constant;
import com.qls.core.entity.DtStore;
import com.qls.core.entity.OpOurRateplanPrice;
import com.qls.lock.RedissonLock;
import com.qls.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author doyoung
 */
@Slf4j
@Service
public class CacheImpl implements Cache {

    /**
     * 分布式锁时间
     */
    private final static int TIME = 15;
    @Autowired
    private RedissonLock redissonLock;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public List<String> getZeroDate(Integer storeId) {
        List<String> zeroDates = (List<String>) redisUtil.hashGet(Constant.Redis.STORE_ZERO_DATE.getValue(), storeId.toString());
        if (Objects.isNull(zeroDates)) {
            return new ArrayList<>();
        }
        return zeroDates;
    }

    @Override
    public List<OpOurRateplanPrice> getStairPrice(Integer crpId) {
        List<OpOurRateplanPrice> opOurRateplanPrices = JSON.parseArray(JSON.toJSONString(redisUtil.hashGet(Constant.Redis.CRPID_USE_CPRICE.getValue(), crpId.toString())), OpOurRateplanPrice.class);
        if (Objects.isNull(opOurRateplanPrices)) {
            return new ArrayList<>();
        }
        return opOurRateplanPrices;
    }

    @Override
    public DtStore getStore(Integer storeId) {
        return (DtStore) redisUtil.hashGet(Constant.Redis.STOREID_USER_STORE.getValue(), storeId.toString());
    }

    @Override
    public boolean delGlobFilterCache(String rpCode, Integer storeId) {
        String h = Constant.Redis.RP_BL_STORE.getValue();
        // 删除全局过滤缓存
        try {
            redissonLock.lock(rpCode, TIME);
            Map<String, Object> mapStoreIds = this.getGlobFilterCache(rpCode);
            if (mapStoreIds.isEmpty()) {
                return true;
            }
            List<Integer> storeIds = (List<Integer>) mapStoreIds.get("storeIds");
            if (storeIds.isEmpty()) {
                redisUtil.hashDel(Constant.Redis.RP_BL_STORE.getValue(), rpCode);
            } else {
                storeIds.remove(storeId);
                if (storeIds.isEmpty()) {
                    redisUtil.hashDel(h, rpCode);
                } else {
                    redisUtil.hashSet(h, rpCode, mapStoreIds);
                }
            }
            return true;
        } catch (Exception e) {
            log.error("店铺ID：{}， rpID：{}，删除全局过滤缓存失败，异常：{}", storeId, rpCode, e.getMessage());
            return false;
        } finally {
            if (redissonLock.isHeldByCurrentThread(rpCode)) {
                redissonLock.unlock(rpCode);
            }
        }
    }

    @Override
    public boolean addGlobFilterCache(String rpCode, Integer storeId, Integer partnerId) {
        String h = Constant.Redis.RP_BL_STORE.getValue();
        List<Integer> storeIds;
        Map<String, Object> mapStore;
        try {
            redissonLock.lock(rpCode, TIME);
            mapStore = (Map<String, Object>) redisUtil.hashGetObject(h, rpCode);
            if (Objects.isNull(mapStore)) {
                mapStore = new HashMap<>();
                storeIds = new ArrayList<>();
            } else {
                storeIds = (List<Integer>) mapStore.get("storeIds");
            }
            if (!storeIds.contains(storeId)) {
                storeIds.add(storeId);
            }
            mapStore.put("storeIds", storeIds);
            mapStore.put("partnerId", partnerId);
            //map.put()
            redisUtil.hashSet(h, rpCode, mapStore);
            return true;
        } catch (Exception e) {
            log.error("店铺ID：{}， rpID：{}，增加全局过滤缓存失败，异常：{}", storeId, rpCode, e.getMessage());
            return false;
        } finally {
            if (redissonLock.isHeldByCurrentThread(rpCode)) {
                redissonLock.unlock(rpCode);
            }
        }
    }

    @Override
    public Map<String, Object> getGlobFilterCache(String rpCode) {
        Map<String, Object> mapStoreIds = (Map<String, Object>) redisUtil.hashGetObject(Constant.Redis.RP_BL_STORE.getValue(), rpCode);
        if (Objects.isNull(mapStoreIds)) {
            return new HashMap<>();
        }
        return mapStoreIds;
    }

    @Override
    public List<Integer> addRpStoreMap(String roomCode, String rpCode, Integer storeId, List<Integer> crpIds, Integer partnerId) {
        String lockName = rpCode + "_" + storeId;
        String h = Constant.Redis.GOODS_BL_CRP_HTL_ROOM_RP_STORE.getValue() + "_" + storeId;
        List<Integer> newCrpIds = new ArrayList<>();
        Map<String, Object> cacheMap;
        try {
            redissonLock.lock(lockName, TIME);
            cacheMap = (Map<String, Object>) redisUtil.hashGet(h, rpCode);
            if (Objects.isNull(cacheMap)) {
                boolean flag = this.addGlobFilterCache(rpCode, storeId, partnerId);
                if (!flag) {
                    return newCrpIds;
                }
                cacheMap = new HashMap<>();
                cacheMap.put("roomCode", roomCode);
                cacheMap.put("crpIds", crpIds);
                newCrpIds.addAll(crpIds);
            } else {
                List<Integer> cacheCrpIds = (List<Integer>) cacheMap.get("crpIds");
                for (Integer crpId : crpIds) {
                    if (cacheCrpIds.contains(crpId)) {
                        continue;
                    }
                    cacheCrpIds.add(crpId);
                    newCrpIds.add(crpId);
                }
            }
            redisUtil.hashSet(h, rpCode, cacheMap);
            return newCrpIds;
        } catch (Exception e) {
            log.error("店铺ID：{}，增加rpId：{}，对应的价格政策失败，异常：{}", storeId, rpCode, e.getMessage());
            return new ArrayList<>();
        } finally {
            if (redissonLock.isHeldByCurrentThread(lockName)) {
                redissonLock.unlock(lockName);
            }
        }
    }

    @Override
    public Map<String, Object> getRpStoreMap(String rpCode, Integer storeId) {
        Map<String, Object> rpStoreCache = new HashMap<>();
        try {
            Map<String, Object> map = (Map<String, Object>) redisUtil.hashGet(Constant.Redis.GOODS_BL_CRP_HTL_ROOM_RP_STORE.getValue() + "_" + storeId, rpCode);
            if (Objects.isNull(map)) {
                this.delGlobFilterCache(rpCode, storeId);
                return rpStoreCache;
            }
            List<Integer> crpIdsCache = (List<Integer>) map.get("crpIds");
            if (Objects.isNull(crpIdsCache) || crpIdsCache.isEmpty()) {
                this.delGlobFilterCache(rpCode, storeId);
                return rpStoreCache;
            }
            return map;
        } catch (Exception e) {
            log.error("店铺ID：{}，查询店铺rp缓存失败：{}，异常：{}", storeId, rpCode, e.getMessage());
            return rpStoreCache;
        }
    }

    @Override
    public boolean delRpStoreMap(String rpCode, Integer storeId, List<Integer> crpIds) {
        String lockName = rpCode + "_" + storeId;
        String h = Constant.Redis.GOODS_BL_CRP_HTL_ROOM_RP_STORE.getValue() + "_" + storeId;
        try {
            redissonLock.lock(lockName, TIME);
            Map<String, Object> cacheMap = (Map<String, Object>) redisUtil.hashGet(h, rpCode);
            if (Objects.isNull(cacheMap)) {
                return true;
            }
            List<Integer> cacheCrpIds = (List<Integer>) cacheMap.get("crpIds");
            if (Objects.isNull(cacheCrpIds) || cacheCrpIds.isEmpty()) {
                return this.delGlobFilterCache(rpCode, storeId);
            }
            cacheCrpIds.removeAll(crpIds);
            if (cacheCrpIds.isEmpty()) {
                redisUtil.hashDel(h, rpCode);
                return this.delGlobFilterCache(rpCode, storeId);
            } else {
                redisUtil.hashSet(h, rpCode, cacheCrpIds);
                return true;
            }
        } catch (Exception e) {
            log.error("店铺ID：{}，删除crpIds：{}，对应的价格政策失败，异常：{}", storeId, crpIds, e.getMessage());
            return false;
        } finally {
            if (redissonLock.isHeldByCurrentThread(lockName)) {
                redissonLock.unlock(lockName);
            }
        }
    }

}
